import 'dart:typed_data';

class Frame {
  List<int> _bytes = [];

  Frame(List<int>? data) {
    if (data != null) {
      _bytes = List.from(data);
    }
  }

  Frame pushByte(int byte) {
    _bytes.add(byte);
    return this;
  }

  Frame pushShort(int short) {
    _bytes.add(short >> 8);
    _bytes.add(short & 0xff);
    return this;
  }

  Frame pushLong(int long) {
    _bytes.add(long >> 24);
    _bytes.add(long >> 16);
    _bytes.add(long >> 8);
    _bytes.add(long & 0xff);
    return this;
  }

  Frame pushList(List<int> data) {
    _bytes.addAll(data);
    return this;
  }

  Frame pushString(String str) {
    _bytes.add(str.length);
    for (var i in str.codeUnits) {
      _bytes.add(i);
    }
    return this;
  }

  int _pop() {
    final ret = _bytes[0];
    _bytes.removeAt(0);
    return ret;
  }

  int popByte() {
    return _pop();
  }

  int popShort() {
    final ret = ((_pop() << 8) & 0xff00) | (_pop() & 0xff);
    return ret;
  }

  int popLong() {
    return ((_pop() << 24) & 0xff000000) |
        ((_pop() << 16) & 0xff0000) |
        ((_pop() << 8) & 0xff00) |
        (_pop() & 0xff);
  }

  List<int> popList(int length) {
    if (_bytes.length < length) {
      return [];
    }
    final ret = _bytes.sublist(0, length);
    _bytes.removeRange(0, length);
    return ret;
  }

  String popString(int length) {
    if (_bytes.length < length) {
      return "";
    }
    final ret = _bytes.sublist(0, length);
    _bytes.removeRange(0, length);
    return String.fromCharCodes(ret);
  }

  List<int> toList() {
    return _bytes;
  }

  int xor() {
    int x = 0;
    for (var i in _bytes) {
      x ^= i;
    }
    return x;
  }

  bool verify() {
    return xor() == 0;
  }

  int get length {
    return _bytes.length;
  }
}
